package com.stars.easyms.base.listener.spring;

import com.stars.easyms.base.bean.LazyLoadBean;
import com.stars.easyms.base.util.ApplicationContextHolder;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.config.*;

/**
 * <p>className: EasyMsSpringValueResolveUtil</p>
 * <p>description: Spring的@Value注解解析类</p>
 *
 * @author guoguifang
 * @version 1.7.3
 * @date 2021/3/22 4:38 下午
 */
class EasyMsSpringValueResolveUtil {

    private static final LazyLoadBean<ConfigurableListableBeanFactory> BEAN_FACTORY =
            new LazyLoadBean<>(() ->
                    (ConfigurableListableBeanFactory) ApplicationContextHolder.getApplicationContext().getAutowireCapableBeanFactory());

    private static final LazyLoadBean<TypeConverter> TYPE_CONVERTER =
            new LazyLoadBean<>(() ->
                    BEAN_FACTORY.getNonNullBean().getTypeConverter());

    static Object resolvePropertyValue(EasyMsSpringValueContext easyMsSpringValueContext, boolean isMethod) {
        ConfigurableListableBeanFactory beanFactory = BEAN_FACTORY.getNonNullBean();
        String strVal = beanFactory.resolveEmbeddedValue(easyMsSpringValueContext.getPlaceholder());
        BeanDefinition bd = (beanFactory.containsBean(easyMsSpringValueContext.getBeanName()) ? beanFactory
                .getMergedBeanDefinition(easyMsSpringValueContext.getBeanName()) : null);
        Object value = evaluateBeanDefinitionString(strVal, bd);
        if (isMethod) {
            value = TYPE_CONVERTER.getNonNullBean()
                    .convertIfNecessary(value, easyMsSpringValueContext.getTargetType(), easyMsSpringValueContext.getMethodParameter());
        } else {
            value = TYPE_CONVERTER.getNonNullBean()
                    .convertIfNecessary(value, easyMsSpringValueContext.getTargetType(), easyMsSpringValueContext.getField());
        }
        return value;
    }

    private static Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition) {
        ConfigurableListableBeanFactory beanFactory = BEAN_FACTORY.getNonNullBean();
        if (beanFactory.getBeanExpressionResolver() == null) {
            return value;
        }
        Scope scope = (beanDefinition != null && beanDefinition.getScope() != null ?
                beanFactory.getRegisteredScope(beanDefinition.getScope()) : null);
        return beanFactory.getBeanExpressionResolver()
                .evaluate(value, new BeanExpressionContext(beanFactory, scope));
    }

    private EasyMsSpringValueResolveUtil() {
    }
}
